/* eslint-disable no-param-reassign */
import { IAppDataEntity, ISearchBar, ISearchBarFilter } from '@ibiz/model-core';
import {
  ValueOP,
  AppCounter,
  IFilterNode,
  isSimpleItems,
  ItemsValueOPs,
  ScriptFactory,
  CounterService,
  calcSearchConds,
  ISearchBarEvent,
  ISearchCondGroup,
  ISearchCondField,
  IFilterNodeField,
  ControlController,
  SearchBarFilterController,
  SearchBarFilterItemsController,
  SearchBarFilterSimpleItemsController,
} from '@ibiz-template/runtime';
import { isNil, isString } from 'lodash-es';
import { createUUID } from 'qx-util';
import { clone } from '@ibiz-template/core';
import { IFilterItem, IEhrSearchBarState } from './ehr-search-bar.state';
import { EhrSearchBarService } from './ehr-search-bar.service';

const ScriptValueRegex = /\$\{[^}]*\}/;

const ExcludeOPs: readonly string[] = [
  ValueOP.IS_NULL,
  ValueOP.IS_NOT_NULL,
  ValueOP.EXISTS,
  ValueOP.NOT_EXISTS,
] as const;

export class EhrSearchBarController extends ControlController<
  ISearchBar,
  IEhrSearchBarState,
  ISearchBarEvent
> {
  /**
   * @description 搜索栏服务
   * @type {EhrSearchBarService}
   * @memberof EhrSearchBarController
   */
  service!: EhrSearchBarService;

  /**
   * @description 应用实体
   * @type {IAppDataEntity}
   * @memberof EhrSearchBarController
   */
  appDataEntity!: IAppDataEntity;

  /**
   * @description 过滤项控制器集合
   * @type {SearchBarFilterController[]}
   * @memberof EhrSearchBarController
   */
  filterControllers: SearchBarFilterController[] = [];

  /**
   * @description 计数器对象
   * @type {AppCounter}
   * @memberof EhrSearchBarController
   */
  counter?: AppCounter;

  /**
   * @description 初始化state的属性
   * @protected
   * @memberof EhrSearchBarController
   */
  protected initState(): void {
    super.initState();
    this.state.filters = [];
    this.state.filterNodes = [];
    this.state.filterItemGroups = [];
    this.state.filterGroups = [];
    this.state.activeFilter = '';
    this.state.activeGroup = '';
  }

  /**
   * @description 生命周期-创建完成
   * @protected
   * @returns {*}  {Promise<void>}
   * @memberof EhrSearchBarController
   */
  protected async onCreated(): Promise<void> {
    this.handleCounterChange = this.handleCounterChange.bind(this);
    await super.onCreated();
    this.appDataEntity = await ibiz.hub.getAppDataEntity(
      this.model.appDataEntityId!,
      this.context.srfappid,
    )!;
    this.service = new EhrSearchBarService(this.model, this.context);
    await this.initSearchBarFilters();
    const { filters } = await this.service.load();
    this.state.filters = filters || [];
    this.initFilterNodes();
    this.initFilterGroup();
    await this.initCounter();
  }

  /**
   * @description 获取过滤参数
   * @returns {*}  {IParams}
   * @memberof EhrSearchBarController
   */
  getFilterParams(): IParams {
    const params: IParams = {};
    const nodes = clone(this.state.filterNodes);
    nodes[0].children = nodes[0].children.filter(n => {
      if (n.nodeType === 'FIELD') {
        const hasError =
          !n.field ||
          !n.valueOP ||
          (!ExcludeOPs.includes(n.valueOP) && !n.value);
        return !hasError;
      }
      return true;
    });
    let searchconds = calcSearchConds(nodes, {
      after: (node, cond) => {
        if (node.nodeType === 'FIELD' && isString(node.value)) {
          if (ScriptValueRegex.test(node.value)) {
            (cond as ISearchCondField).value = ScriptFactory.execSingleLine(
              `\`${node.value}\``,
              {
                ...this.getEventArgs(),
              },
            );
          }
        }
      },
    });
    const filterconds = this.state.filterGroups.find(
      group => this.state.activeGroup === group.key,
    )?.searchconds;
    if (filterconds) {
      if (searchconds) {
        (searchconds[0] as ISearchCondGroup).searchconds?.push(...filterconds);
      } else {
        searchconds = filterconds;
      }
    }
    if (searchconds) Object.assign(params, { searchconds });
    return params;
  }

  /**
   * @description 根据节点数据查找过滤项控制器
   * @param {(IFilterNodeField | IFilterNodeItems)} node
   * @returns {*}  {(SearchBarFilterController | undefined)}
   * @memberof EhrSearchBarController
   */
  findFilterControllerByNode(
    node: IFilterNodeField,
  ): SearchBarFilterController | undefined {
    return this.filterControllers.find(item => {
      if (item.type === 'SIMPLE_ITEMS') return false;
      if (item.fieldName === node.field)
        return item.valueOP ? item.valueOP === node.valueOP : true;
      return false;
    });
  }

  /**
   * @description 处理计数器值变更
   * @protected
   * @memberof EhrSearchBarController
   */
  protected handleCounterChange(): void {
    if (!this.counter) return;
    this.state.filterGroups.forEach(filter => {
      const { counterId, counterMode } = filter;
      if (counterId) {
        const count = this.counter!.getCounter(counterId);
        filter.count = count;
        if (counterMode === 1 && count === 0) filter.visible = false;
      }
    });
  }

  /**
   * @description 初始化过滤项控制器
   * @protected
   * @returns {*}  {Promise<void>}
   * @memberof EhrSearchBarController
   */
  protected async initSearchBarFilters(): Promise<void> {
    const { searchBarFilters } = this.model;
    if (!searchBarFilters || !searchBarFilters.length) return;
    const itemsMap = new Map<string, ISearchBarFilter[]>();
    searchBarFilters.forEach(item => {
      // 整理exists或者NOTEXISTS的模型
      if (
        item.defsearchMode?.valueOP &&
        ItemsValueOPs.includes(item.defsearchMode.valueOP)
      ) {
        if (isSimpleItems(item)) {
          this.filterControllers.push(
            new SearchBarFilterSimpleItemsController(
              item,
              this.appDataEntity,
              this.context,
              this.params,
            ),
          );
          return;
        }

        const key = `${item.appDEFieldId}_${item.defsearchMode.valueOP}`;
        if (!itemsMap.has(key)) {
          itemsMap.set(key, []);
        }
        itemsMap.get(key)!.push(item);
        return;
      }

      // 常规的属性过滤项
      const filterController = new SearchBarFilterController(
        item,
        this.appDataEntity,
        this.context,
        this.params,
      );
      this.filterControllers.push(filterController);
    });

    // 初始化SearchBarFilterItemsController
    if (itemsMap.size > 0) {
      itemsMap.forEach(items => {
        const filterController = new SearchBarFilterItemsController(
          items,
          this.appDataEntity,
          this.context,
          this.params,
        );
        this.filterControllers.push(filterController);
      });
    }

    await Promise.all(
      this.filterControllers.map(controller => controller.init()),
    );
  }

  /**
   * @description 初始化计数器
   * @protected
   * @returns {*}  {Promise<void>}
   * @memberof EhrSearchBarController
   */
  protected async initCounter(): Promise<void> {
    if (!this.state.isCounterDisabled) {
      const { appCounterRefs } = this.model as IData;
      const appCounterRef = appCounterRefs?.[0];
      if (appCounterRef) {
        this.counter = await CounterService.getCounterByRef(
          appCounterRef,
          this.context,
          { ...this.params },
        );
      }
      this.counter?.onChange(this.handleCounterChange, false);
    }
    this.handleCounterChange();
    this.initDefaultActiveGroup();
  }

  /**
   * @description 初始化默认激活分组
   * @protected
   * @returns {*}  {void}
   * @memberof EhrSearchBarController
   */
  protected initDefaultActiveGroup(): void {
    if (!this.state.filterGroups.length) return;
    const filterGroups = this.state.filterGroups.filter(group => group.visible);
    this.state.activeGroup =
      filterGroups.find(item => item.defaultSelect)?.key || filterGroups[0].key;
  }

  /**
   * @description 初始化过滤节点分组数据
   * @protected
   * @memberof EhrSearchBarController
   */
  protected initFilterNodes(): void {
    const { groupMode } = this.model;
    const children: IFilterNode[] =
      this.filterControllers
        .filter(filter => filter.model.userParam?.defaultShow === 'true')
        .map(filter => {
          return {
            nodeType: 'FIELD',
            field: filter.key,
            valueOP: filter.valueOP as ValueOP,
            value: null,
          };
        }) || [];
    this.state.filterNodes = [
      {
        children,
        nodeType: 'GROUP',
        logicType: groupMode === 'OR' ? 'OR' : 'AND',
      },
    ];
  }

  /**
   * @description 初始化过滤分组数据
   * - 初始化过滤项的分组集合和过滤分组条件
   * @protected
   * @memberof EhrSearchBarController
   */
  protected initFilterGroup(): void {
    const filterItems = this.filterControllers.map(filter => ({
      key: filter.key,
      caption: filter.label,
      selected: filter.model.userParam?.defaultShow === 'true',
    }));
    const { searchBarGroups } = this.model;
    const itemGroups: { groupName: string; keys: string[] }[] = [];
    this.state.filterGroups = [];
    searchBarGroups?.forEach(item => {
      if (item.data)
        try {
          const defaultShow = item.userParam?.defaultShow === 'true';
          const data = JSON.parse(item.data);
          if (data.theme_model.searchconds) {
            const searchconds = data.theme_model.searchconds;
            if (defaultShow) {
              this.state.filterGroups.push({
                searchconds,
                key: item.id!,
                visible: true,
                count: undefined,
                caption: item.caption!,
                counterId: item.counterId,
                counterMode: item.counterMode,
                defaultSelect: item.defaultGroup || false,
              });
            } else {
              const keys =
                searchconds[0]?.searchconds?.map(
                  (cond: IData) => cond.fieldname,
                ) || [];
              itemGroups.push({ groupName: item.caption!, keys });
            }
          }
        } catch (error) {
          ibiz.log.error(
            ibiz.i18n.t('runtime.controller.control.searchBar.JSONFormat', {
              data: item.data,
            }),
            error,
          );
        }
    });
    const groupMap = filterItems.reduce((map, item) => {
      const groupName =
        itemGroups.find(group => group.keys.includes(item.key))?.groupName ||
        '未分类';
      const children = map.get(groupName) || [];
      return map.set(groupName, [...children, item]);
    }, new Map<string, IFilterItem[]>());
    const filterItemGroups = [...groupMap.entries()].map(
      ([caption, children]) => ({
        caption,
        children,
      }),
    );
    const index = filterItemGroups.findIndex(
      group => group.caption === '未分类',
    );
    if (index !== -1) {
      const removedItem = filterItemGroups.splice(index, 1)[0];
      filterItemGroups.push(removedItem);
    }
    this.state.filterItemGroups = filterItemGroups;
  }

  /**
   * @description 处理过滤改变
   * @param {string} key
   * @memberof EhrSearchBarController
   */
  handleFilterChange(key: string): void {
    this.state.activeFilter = key;
    const filter = this.state.filters.find(item => item.key === key);
    if (filter) {
      const { groupMode } = this.model;
      // 当前模型有的才有效
      const children: IFilterNode[] = filter.filterNodeFields.filter(
        item => !!this.findFilterControllerByNode(item),
      );
      this.state.filterNodes = [
        {
          children,
          nodeType: 'GROUP',
          logicType: groupMode === 'OR' ? 'OR' : 'AND',
        },
      ];
    } else {
      this.initFilterNodes();
    }
    this.onSearch();
  }

  /**
   * @description 处理过滤项改变
   * @param {string} key 过滤项标识
   * @param {boolean} state
   * @memberof EhrSearchBarController
   */
  handleFilterItemChange(key: string, state: boolean): void {
    const controller = this.filterControllers.find(c => c.key === key);
    if (!controller) return;
    for (const group of this.state.filterItemGroups) {
      const item = group.children.find(child => child.key === key);
      if (item) {
        item.selected = state;
        break;
      }
    }
    const filterNodes = this.state.filterNodes[0]
      .children as IFilterNodeField[];
    if (state) {
      filterNodes.push({
        nodeType: 'FIELD',
        field: controller.key,
        valueOP: controller.valueOP as ValueOP,
        value: null,
      });
    } else {
      this.state.filterNodes[0].children = filterNodes.filter(
        node => node.field !== key,
      );
      this.onSearch();
    }
  }

  /**
   * @description 搜索
   * @memberof EhrSearchBarController
   */
  onSearch(): void {
    this.evt.emit('onSearch', undefined);
  }

  /**
   * @description 重置
   * @memberof EhrSearchBarController
   */
  onReset(): void {
    this.handleFilterChange(this.state.activeFilter);
    this.onSearch();
  }

  /**
   * @description 保存过滤条件
   * @param {string} caption
   * @returns {*}  {Promise<void>}
   * @memberof EhrSearchBarController
   */
  async onSaveFilter(caption: string): Promise<void> {
    const key = createUUID();
    const filter = {
      key,
      caption,
      filterNodeFields: this.state.filterNodes[0]
        .children as IFilterNodeField[],
    };
    this.state.filters.push(filter);
    await this.service.save({ filters: this.state.filters });
    this.state.activeFilter = key;
  }

  /**
   * @description 删除过滤条件
   * @param {string} key
   * @returns {*}  {Promise<void>}
   * @memberof EhrSearchBarController
   */
  async onRemoveFilter(key: string): Promise<void> {
    const index = this.state.filters.findIndex(filter => filter.key === key);
    if (index !== -1) {
      this.state.filters.splice(index, 1);
      await this.service.save({ filters: this.state.filters });
      if (this.state.activeFilter === key) {
        this.state.activeFilter = '';
        this.initFilterNodes();
      }
    }
  }

  /**
   * @description 销毁
   * @protected
   * @returns {*}  {Promise<void>}
   * @memberof EhrSearchBarController
   */
  protected async onDestroyed(): Promise<void> {
    await super.onDestroyed();
    this.counter?.destroy();
    this.counter?.offChange(this.handleCounterChange);
  }
}
